package com.wangzhixuan.commons.sqlparser;

import java.util.HashSet;

import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Sets;
import com.wangzhixuan.commons.shiro.ShiroUser;

import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.Between;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.GreaterThan;
import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.FromItemVisitor;
import net.sf.jsqlparser.statement.select.LateralSubSelect;
import net.sf.jsqlparser.statement.select.SubJoin;
import net.sf.jsqlparser.statement.select.SubSelect;
import net.sf.jsqlparser.statement.select.TableFunction;
import net.sf.jsqlparser.statement.select.ValuesList;

public class FromItemVisitorImpl implements FromItemVisitor {

    private static Logger logger = LoggerFactory.getLogger(FromItemVisitorImpl.class);
    // 声明增强条件
    private Expression enhancedCondition;
    
    // 定义需要数据隔离的表
    private static HashSet<String> interceptTableSet = Sets.newHashSet();
    static {
    	interceptTableSet.add("ITEM");//商品管理数据隔离; 同时item 表中新增  company_id 字段
        interceptTableSet.add("ITEM_SKU");//SKU管理数据隔离;
    	interceptTableSet.add("INVENTORY");//SKU 管理展示库存
    	interceptTableSet.add("BRAND");//品牌管理
    	interceptTableSet.add("OUTER_ORDER");//主订单管理
    	interceptTableSet.add("OUTER_ORDER_DETAIL");// 主订单明细管理
    	interceptTableSet.add("ERP_ORDER");//子订单管理
    	interceptTableSet.add("TASK_DAILY");//采购单
    	interceptTableSet.add("TASK_DAILY_DETAIL");//采购单明细
    	interceptTableSet.add("PURCHASE_STORAGE");//采购入库单
    	interceptTableSet.add("PURCHASE_STORAGE_DETAIL");//采购入库单明细
    	interceptTableSet.add("INVENTORY_AREA");//库存占用表
    	interceptTableSet.add("INVENTORY_OUT");//库存记录库记录表
    	interceptTableSet.add("WAREHOUSE");//仓库改造
    	interceptTableSet.add("INVENTORY_INOUT");//出入库记录表     {硬编码}	
        //interceptTableSet.add("SHIPPING_ORDER");//发货管理              {硬编码}
        //interceptTableSet.add("TASK_DAILY_ORDER");//订单生成采购单              {硬编码}
    	//interceptTableSet.add("TASK_DAILY_ORDER_HISTORY");// 订单生成采购单历史记录  {硬编码}
    	interceptTableSet.add("TASK_DAILY_ORDER_UNCOMPLETE"); //未完成采购表
    	interceptTableSet.add("ERP_RETURN_ORDER"); //退单表
    	interceptTableSet.add("SELLER_TYPE");//销售类别表
    	interceptTableSet.add("SELLER");//销售人员表
    	//interceptTableSet.add("WX_PURCHASE_USER");//买手人员表
    	interceptTableSet.add("GOODS_CASE");//货源信息反馈表
    	interceptTableSet.add("LOGISTIC_COMPANY");//快递公司
    	interceptTableSet.add("RECEIPT");//小票
    	interceptTableSet.add("RECEIPT_GROUP");//小票另存表
    	interceptTableSet.add("TASK_RECEIPT");//小票明细
    	interceptTableSet.add("FIND_ITEM");//发现商品
    	interceptTableSet.add("FIND_ITEM_SKU");//发现商品sku
    	interceptTableSet.add("FILE_MANAGE");//文件管理
    	interceptTableSet.add("LOGISTIC_TYPE");//物流线路
    }

    // FROM 表名 <----主要的就是这个，判断用户对这个表有没有权限
    @Override
    public void visit(Table tableName) {
        //判断该表是否是需要操作的表
        if (isActionTable(tableName.getFullyQualifiedName())) {
            // 声明表达式数组
            Expression[] expressions;
            // 其他情况,也就是最常用的情况，比如where   1 = 1
            Column column = new Column(new Table(tableName.getAlias()!=null?tableName.getAlias().getName():tableName.getFullyQualifiedName()), "company_id");
            if(getShiroUser()== null){
            	return;
            }else {
            	expressions = new Expression[] {column, new LongValue(getShiroUser().getCompanyId())};
            }
            // 根据运算符对原始数据进行拼接
            Expression operator = this.getOperator("=", expressions);
            if (this.enhancedCondition != null) {
                enhancedCondition = new AndExpression(enhancedCondition , operator);
            } else {
                enhancedCondition = operator;
            }
        }
    }

    // FROM 子查询
    @Override
    public void visit(SubSelect subSelect) {
        // 如果是子查询的话返回到select接口实现类
        subSelect.getSelectBody().accept(new SelectVisitorImpl());
    }

    // FROM subjoin
    @Override
    public void visit(SubJoin subjoin) {
        subjoin.getLeft().accept(new FromItemVisitorImpl());
        subjoin.getJoin().getRightItem().accept(new FromItemVisitorImpl());
    }

    // FROM 横向子查询
    @Override
    public void visit(LateralSubSelect lateralSubSelect) {
        lateralSubSelect.getSubSelect().getSelectBody()
                .accept(new SelectVisitorImpl());
    }

    // FROM value列表
    @Override
    public void visit(ValuesList valuesList) {
    }

    // FROM tableFunction
    @Override
    public void visit(TableFunction tableFunction) {
    }

    // 将字符串类型的运算符转换成数据库运算语句
    private Expression getOperator(String op, Expression[] exp) {
        if ("=".equals(op)) {
            EqualsTo eq = new EqualsTo();
            eq.setLeftExpression(exp[0]);
            eq.setRightExpression(exp[1]);
            return eq;
        } else if (">".equals(op)) {
            GreaterThan gt = new GreaterThan();
            gt.setLeftExpression(exp[0]);
            gt.setRightExpression(exp[1]);
            return gt;
        } else if (">=".equals(op)) {
            GreaterThanEquals geq = new GreaterThanEquals();
            geq.setLeftExpression(exp[0]);
            geq.setRightExpression(exp[1]);
            return geq;
        } else if ("<".equals(op)) {
            MinorThan mt = new MinorThan();
            mt.setLeftExpression(exp[0]);
            mt.setRightExpression(exp[1]);
            return mt;
        } else if ("<=".equals(op)) {
            MinorThanEquals leq = new MinorThanEquals();
            leq.setLeftExpression(exp[0]);
            leq.setRightExpression(exp[1]);
            return leq;
        } else if ("<>".equals(op)) {
            NotEqualsTo neq = new NotEqualsTo();
            neq.setLeftExpression(exp[0]);
            neq.setRightExpression(exp[1]);
            return neq;
        } else if ("is null".equalsIgnoreCase(op)) {
            IsNullExpression isNull = new IsNullExpression();
            isNull.setNot(false);
            isNull.setLeftExpression(exp[0]);
            return isNull;
        } else if ("is not null".equalsIgnoreCase(op)) {
            IsNullExpression isNull = new IsNullExpression();
            isNull.setNot(true);
            isNull.setLeftExpression(exp[0]);
            return isNull;
        } else if ("like".equalsIgnoreCase(op)) {
            LikeExpression like = new LikeExpression();
            like.setNot(false);
            like.setLeftExpression(exp[0]);
            like.setRightExpression(exp[1]);
            return like;
        } else if ("not like".equalsIgnoreCase(op)) {
            LikeExpression nlike = new LikeExpression();
            nlike.setNot(true);
            nlike.setLeftExpression(exp[0]);
            nlike.setRightExpression(exp[1]);
            return nlike;
        } else if ("between".equalsIgnoreCase(op)) {
            Between bt = new Between();
            bt.setNot(false);
            bt.setLeftExpression(exp[0]);
            bt.setBetweenExpressionStart(exp[1]);
            bt.setBetweenExpressionEnd(exp[2]);
            return bt;
        } else if ("not between".equalsIgnoreCase(op)) {
            Between bt = new Between();
            bt.setNot(true);
            bt.setLeftExpression(exp[0]);
            bt.setBetweenExpressionStart(exp[1]);
            bt.setBetweenExpressionEnd(exp[2]);
            return bt;
        } else {
            // 如果没有该运算符对应的语句
            return null;
        }

    }

    public Expression getEnhancedCondition() {
        return enhancedCondition;
    }

    // 判断传入的table是否是要进行操作的table
    public boolean isActionTable(String tableName) {
        boolean flag = false;
        if (interceptTableSet.contains(tableName.replaceAll("`", "").toUpperCase())) {
            flag = true;
        }
        return flag;
    }
    
    /**
     * 获取当前登录用户对象
     * @return {ShiroUser}
     */
    public ShiroUser getShiroUser() {
    	ShiroUser one = (ShiroUser) SecurityUtils.getSubject().getPrincipal();
        return one;
    }

}
